﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using HslCommunication.Core.Net;
using HslCommunication.LogNet;

namespace HslCommunication.Enthernet
{
	/// <summary>
	/// 发布订阅服务器的类，支持按照关键字进行数据信息的订阅
	/// </summary>
	/// <remarks>
	/// 详细的使用说明，请参照博客<a href="http://www.cnblogs.com/dathlin/p/8992315.html">http://www.cnblogs.com/dathlin/p/8992315.html</a>
	/// </remarks>
	/// <example>
	/// 此处贴上了Demo项目的服务器配置的示例代码
	/// <code lang="cs" source="TestProject\PushNetServer\FormServer.cs" region="NetPushServer" title="NetPushServer示例" />
	/// </example>
	// Token: 0x020000FC RID: 252
	public class NetPushServer : NetworkServerBase
	{
		/// <summary>
		/// 实例化一个对象
		/// </summary>
		// Token: 0x06001521 RID: 5409 RVA: 0x0006DC48 File Offset: 0x0006BE48
		public NetPushServer()
		{
			this.dictPushClients = new Dictionary<string, PushGroupClient>();
			this.dictSendHistory = new Dictionary<string, string>();
			this.dicHybirdLock = new object();
			this.dicSendCacheLock = new object();
			this.sendAction = new Action<AppSession, string>(this.SendString);
			this.pushClientsLock = new object();
			this.pushClients = new List<NetPushClient>();
		}

		/// <inheritdoc />
		// Token: 0x06001522 RID: 5410 RVA: 0x0006DCC0 File Offset: 0x0006BEC0
		protected override void ThreadPoolLogin(Socket socket, IPEndPoint endPoint)
		{
			OperateResult<int, string> operateResult = base.ReceiveStringContentFromSocket(socket, 30000);
			bool flag = !operateResult.IsSuccess;
			if (!flag)
			{
				OperateResult operateResult2 = base.SendStringAndCheckReceive(socket, 0, "");
				bool flag2 = !operateResult2.IsSuccess;
				if (!flag2)
				{
					AppSession appSession = new AppSession
					{
						KeyGroup = operateResult.Content2,
						WorkSocket = socket
					};
					appSession.IpEndPoint = endPoint;
					appSession.IpAddress = endPoint.Address.ToString();
					try
					{
						socket.BeginReceive(appSession.BytesHead, 0, appSession.BytesHead.Length, SocketFlags.None, new AsyncCallback(this.ReceiveCallback), appSession);
					}
					catch (Exception ex)
					{
						ILogNet logNet = base.LogNet;
						if (logNet != null)
						{
							logNet.WriteException(this.ToString(), StringResources.Language.SocketReceiveException, ex);
						}
						return;
					}
					ILogNet logNet2 = base.LogNet;
					if (logNet2 != null)
					{
						logNet2.WriteDebug(this.ToString(), string.Format(StringResources.Language.ClientOnlineInfo, appSession.IpEndPoint));
					}
					PushGroupClient pushGroupClient = this.GetPushGroupClient(operateResult.Content2);
					bool flag3 = pushGroupClient != null;
					if (flag3)
					{
						Interlocked.Increment(ref this.onlineCount);
						pushGroupClient.AddPushClient(appSession);
						object obj = this.dicSendCacheLock;
						lock (obj)
						{
							bool flag5 = this.dictSendHistory.ContainsKey(operateResult.Content2);
							if (flag5)
							{
								bool flag6 = this.isPushCacheAfterConnect;
								if (flag6)
								{
									this.SendString(appSession, this.dictSendHistory[operateResult.Content2]);
								}
							}
						}
					}
				}
			}
		}

		/// <inheritdoc />
		// Token: 0x06001523 RID: 5411 RVA: 0x0006DE74 File Offset: 0x0006C074
		public override void ServerClose()
		{
			base.ServerClose();
		}

		/// <summary>
		/// 主动推送数据内容
		/// </summary>
		/// <param name="key">关键字</param>
		/// <param name="content">数据内容</param>
		// Token: 0x06001524 RID: 5412 RVA: 0x0006DE80 File Offset: 0x0006C080
		public void PushString(string key, string content)
		{
			object obj = this.dicSendCacheLock;
			lock (obj)
			{
				bool flag2 = this.dictSendHistory.ContainsKey(key);
				if (flag2)
				{
					this.dictSendHistory[key] = content;
				}
				else
				{
					this.dictSendHistory.Add(key, content);
				}
			}
			this.AddPushKey(key);
			PushGroupClient pushGroupClient = this.GetPushGroupClient(key);
			if (pushGroupClient != null)
			{
				pushGroupClient.PushString(content, this.sendAction);
			}
		}

		/// <summary>
		/// 移除关键字信息，通常应用于一些特殊临时用途的关键字
		/// </summary>
		/// <param name="key">关键字</param>
		// Token: 0x06001525 RID: 5413 RVA: 0x0006DF14 File Offset: 0x0006C114
		public void RemoveKey(string key)
		{
			object obj = this.dicHybirdLock;
			lock (obj)
			{
				bool flag2 = this.dictPushClients.ContainsKey(key);
				if (flag2)
				{
					int num = this.dictPushClients[key].RemoveAllClient();
					for (int i = 0; i < num; i++)
					{
						Interlocked.Decrement(ref this.onlineCount);
					}
					this.dictPushClients.Remove(key);
				}
			}
		}

		/// <summary>
		/// 创建一个远程服务器的数据推送操作，以便推送给子客户端
		/// </summary>
		/// <param name="ipAddress">远程的IP地址</param>
		/// <param name="port">远程的端口号</param>
		/// <param name="key">订阅的关键字</param>
		// Token: 0x06001526 RID: 5414 RVA: 0x0006DFA8 File Offset: 0x0006C1A8
		public OperateResult CreatePushRemote(string ipAddress, int port, string key)
		{
			object obj = this.pushClientsLock;
			OperateResult operateResult;
			lock (obj)
			{
				bool flag2 = this.pushClients.Find((NetPushClient m) => m.KeyWord == key) == null;
				if (flag2)
				{
					NetPushClient netPushClient = new NetPushClient(ipAddress, port, key);
					operateResult = netPushClient.CreatePush(new Action<NetPushClient, string>(this.GetPushFromServer));
					bool isSuccess = operateResult.IsSuccess;
					if (isSuccess)
					{
						this.pushClients.Add(netPushClient);
					}
				}
				else
				{
					operateResult = new OperateResult(StringResources.Language.KeyIsExistAlready);
				}
			}
			return operateResult;
		}

		/// <summary>
		/// 在线客户端的数量
		/// </summary>
		// Token: 0x170004FC RID: 1276
		// (get) Token: 0x06001527 RID: 5415 RVA: 0x0006E070 File Offset: 0x0006C270
		public int OnlineCount
		{
			get
			{
				return this.onlineCount;
			}
		}

		/// <summary>
		/// 在客户端上线之后，是否推送缓存的数据，默认设置为true
		/// </summary>
		// Token: 0x170004FD RID: 1277
		// (get) Token: 0x06001528 RID: 5416 RVA: 0x0006E078 File Offset: 0x0006C278
		// (set) Token: 0x06001529 RID: 5417 RVA: 0x0006E090 File Offset: 0x0006C290
		public bool PushCacheAfterConnect
		{
			get
			{
				return this.isPushCacheAfterConnect;
			}
			set
			{
				this.isPushCacheAfterConnect = value;
			}
		}

		// Token: 0x0600152A RID: 5418 RVA: 0x0006E09C File Offset: 0x0006C29C
		private void ReceiveCallback(IAsyncResult ar)
		{
			AppSession appSession = ar.AsyncState as AppSession;
			bool flag = appSession != null;
			if (flag)
			{
				try
				{
					Socket workSocket = appSession.WorkSocket;
					int num = workSocket.EndReceive(ar);
					bool flag2 = num <= 4;
					if (flag2)
					{
						ILogNet logNet = base.LogNet;
						if (logNet != null)
						{
							logNet.WriteDebug(this.ToString(), string.Format(StringResources.Language.ClientOfflineInfo, appSession.IpEndPoint));
						}
						this.RemoveGroupOnline(appSession.KeyGroup, appSession.ClientUniqueID);
					}
					else
					{
						appSession.HeartTime = DateTime.Now;
					}
				}
				catch (Exception ex)
				{
					bool flag3 = ex.Message.Contains(StringResources.Language.SocketRemoteCloseException);
					if (flag3)
					{
						ILogNet logNet2 = base.LogNet;
						if (logNet2 != null)
						{
							logNet2.WriteDebug(this.ToString(), string.Format(StringResources.Language.ClientOfflineInfo, appSession.IpEndPoint));
						}
						this.RemoveGroupOnline(appSession.KeyGroup, appSession.ClientUniqueID);
					}
					else
					{
						ILogNet logNet3 = base.LogNet;
						if (logNet3 != null)
						{
							logNet3.WriteException(this.ToString(), string.Format(StringResources.Language.ClientOfflineInfo, appSession.IpEndPoint), ex);
						}
						this.RemoveGroupOnline(appSession.KeyGroup, appSession.ClientUniqueID);
					}
				}
			}
		}

		// Token: 0x0600152B RID: 5419 RVA: 0x0006E1F4 File Offset: 0x0006C3F4
		private void AddPushKey(string key)
		{
			object obj = this.dicHybirdLock;
			lock (obj)
			{
				bool flag2 = !this.dictPushClients.ContainsKey(key);
				if (flag2)
				{
					this.dictPushClients.Add(key, new PushGroupClient());
				}
			}
		}

		// Token: 0x0600152C RID: 5420 RVA: 0x0006E25C File Offset: 0x0006C45C
		private PushGroupClient GetPushGroupClient(string key)
		{
			PushGroupClient pushGroupClient = null;
			object obj = this.dicHybirdLock;
			lock (obj)
			{
				bool flag2 = this.dictPushClients.ContainsKey(key);
				if (flag2)
				{
					pushGroupClient = this.dictPushClients[key];
				}
				else
				{
					pushGroupClient = new PushGroupClient();
					this.dictPushClients.Add(key, pushGroupClient);
				}
			}
			return pushGroupClient;
		}

		/// <summary>
		/// 移除客户端的数据信息
		/// </summary>
		/// <param name="key">指定的客户端</param>
		/// <param name="clientID">指定的客户端唯一的id信息</param>
		// Token: 0x0600152D RID: 5421 RVA: 0x0006E2DC File Offset: 0x0006C4DC
		private void RemoveGroupOnline(string key, string clientID)
		{
			PushGroupClient pushGroupClient = this.GetPushGroupClient(key);
			bool flag = pushGroupClient != null;
			if (flag)
			{
				bool flag2 = pushGroupClient.RemovePushClient(clientID);
				if (flag2)
				{
					Interlocked.Decrement(ref this.onlineCount);
				}
			}
		}

		// Token: 0x0600152E RID: 5422 RVA: 0x0006E318 File Offset: 0x0006C518
		private void SendString(AppSession appSession, string content)
		{
			bool flag = !base.Send(appSession.WorkSocket, HslProtocol.CommandBytes(0, base.Token, content)).IsSuccess;
			if (flag)
			{
				this.RemoveGroupOnline(appSession.KeyGroup, appSession.ClientUniqueID);
			}
		}

		// Token: 0x0600152F RID: 5423 RVA: 0x0006E360 File Offset: 0x0006C560
		private void GetPushFromServer(NetPushClient pushClient, string data)
		{
			this.PushString(pushClient.KeyWord, data);
		}

		/// <inheritdoc />
		// Token: 0x06001530 RID: 5424 RVA: 0x0006E371 File Offset: 0x0006C571
		public override string ToString()
		{
			return string.Format("NetPushServer[{0}]", base.Port);
		}

		// Token: 0x0400050B RID: 1291
		private Dictionary<string, string> dictSendHistory;

		// Token: 0x0400050C RID: 1292
		private Dictionary<string, PushGroupClient> dictPushClients;

		// Token: 0x0400050D RID: 1293
		private readonly object dicHybirdLock;

		// Token: 0x0400050E RID: 1294
		private readonly object dicSendCacheLock;

		// Token: 0x0400050F RID: 1295
		private Action<AppSession, string> sendAction;

		// Token: 0x04000510 RID: 1296
		private int onlineCount = 0;

		// Token: 0x04000511 RID: 1297
		private List<NetPushClient> pushClients;

		// Token: 0x04000512 RID: 1298
		private object pushClientsLock;

		// Token: 0x04000513 RID: 1299
		private bool isPushCacheAfterConnect = true;
	}
}
